{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "d1f20875-c50d-46df-906b-49ec1d0c6002",
   "metadata": {},
   "source": [
    "# 8.4 使用SGD优化器训练模型\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c90a18b9-d8e8-431c-856c-35f1e4ed05e1",
   "metadata": {},
   "source": [
    "### 1.任务描述\n",
    "\n",
    "要求：\n",
    "\n",
    "1. 使用鸢尾花数据集构建一层神经网络，实现鸢尾花的分类\n",
    "   \n",
    "2. 使用Python原生代码实现SGD优化器，对模型参数进行优化，打印迭代损失。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f5b4fc39-cbcf-432a-bf1e-e75e642d4b87",
   "metadata": {},
   "source": [
    "### 2.知识准备\n",
    "\n",
    "见教程。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c1d0295a-4ac4-470a-8263-027a3d69ac2c",
   "metadata": {},
   "source": [
    "### 3.任务分析\n",
    "\n",
    "在鸢尾花的分类中，使用SGD优化器更新参数的用法为：$w_{t+1}=w_t-lr*g_t$。系数。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "435c6090-cfda-4f46-a550-22a368e41e4a",
   "metadata": {},
   "source": [
    "### 4.任务实施\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ec75eb6c-5da3-467d-a471-ca3b47242dd6",
   "metadata": {},
   "source": [
    "执行代码"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2ae9da58-e339-4d22-9f8d-ca255711d89e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0, loss: 0.29733049869537354\n",
      "Epoch 100, loss: 0.059718817472457886\n",
      "Epoch 200, loss: 0.04109456837177276\n",
      "Epoch 300, loss: 0.0331419762223959\n",
      "Epoch 400, loss: 0.028768228366971016\n",
      "Epoch 500, loss: 0.02589208334684372\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from sklearn import datasets\n",
    "import numpy as np\n",
    "import time\n",
    "# 导入鸢尾花数据集\n",
    "x_data = datasets.load_iris().data\n",
    "y_data = datasets.load_iris().target\n",
    "\n",
    "np.random.seed(116)  \n",
    "np.random.shuffle(x_data)\n",
    "np.random.seed(116)\n",
    "np.random.shuffle(y_data)\n",
    "\n",
    "x_data = tf.cast(x_data, tf.float32)\n",
    "train_db = tf.data.Dataset.from_tensor_slices((x_data, y_data)).batch(32)\n",
    "# 构建一层神经网络，实现鸢尾花的分类\n",
    "tf.random.set_seed(116)\n",
    "w1 = tf.Variable(tf.random.truncated_normal([4, 3], stddev=0.1, seed=1))\n",
    "b1 = tf.Variable(tf.random.truncated_normal([3], stddev=0.1, seed=1))\n",
    "\n",
    "lr = 0.1\n",
    "epoch = 500\n",
    "loss_all = 0\n",
    "for epoch in range(0,epoch+1):\n",
    "    for step, (x_train, y_train) in enumerate(train_db):  \n",
    "        with tf.GradientTape() as tape:\n",
    "            y = tf.matmul(x_train, w1) + b1\n",
    "            y = tf.nn.softmax(y)\n",
    "            y_ = tf.one_hot(y_train, depth=3)\n",
    "            loss = tf.reduce_mean(tf.square(y_ - y))            \n",
    "        loss_all += loss.numpy()\n",
    "        grads = tape.gradient(loss, [w1, b1])\n",
    "        # 实现梯度更新\n",
    "        w1.assign_sub(lr * grads[0]) \n",
    "        b1.assign_sub(lr * grads[1]) \n",
    "    if epoch % 100==0:\n",
    "        print(\"Epoch {}, loss: {}\".format(epoch, loss_all / 5))\n",
    "    loss_all = 0  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3b3e36e-8418-4caf-af51-d8ac80e2a321",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
